package com.xiaoq.matrix.weixin.endpoint;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import com.xiaoq.coms.util.JsonUtil;
import com.xiaoq.coms.util.MapUtil;
import com.xiaoq.matrix.weixin.WXAddMaterialResponse;
import com.xiaoq.matrix.weixin.WXUploadImageResponse;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@RestController
@RequestMapping("/api/v1/weixin")
public class WXMaterialEndpoint {
	private static final Logger LOG = LoggerFactory.getLogger(WXMaterialEndpoint.class);
	
	private static final String URL_UPLOAD_IMAGE = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={0}";
	private static final String URL_UPLOAD_TMP_MEDIA = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={0}&type={1}";
	private static final String URL_GET_TMP_MEDIA = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={0}&media_id={1}";
	private static final String URL_ADD_MATERIAL = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={0}&type={1}";
	private static final String URL_GET_MATERIAL = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token={0}";
	private static final String URL_ADD_NEWS = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token={0}";
	private static final String URL_GET_NEWS = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={0}";
	private static final String URL_GET_MATERIAL_COUNT = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token={0}";
	
	/*
	 * 本接口所上传的图片不占用公众号的素材库中图片数量的5000个的限制。图片仅支持jpg/png格式，大小必须在1MB以下。
	 */
	@ApiOperation(value = "上传图文消息内的图片获取URL", notes = "上传图文消息内的图片获取URL，不受5000限制")
	@ApiResponses({ @ApiResponse(code = 200, response = WXUploadImageResponse.class, message = "上传结果") })
	@PostMapping(value = "/media/uploadimg", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public ResponseEntity<?> uploadImage(@RequestPart(value = "file", required = false) @ApiParam(value = "文件", required = false) MultipartFile file, 
			@RequestPart(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = false) String accessToken,
			HttpServletRequest request) {
//	    RestTemplate rest = new RestTemplate();
//	    if (file == null || file.isEmpty()) {
//	    	throw new RuntimeException("未上传文件或上传了空文件");
//	    }
//	    FileSystemResource resource = new FileSystemResource(file.getName());
//	    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();  
//	    param.add("media", resource);
//	    String respStr = rest.postForObject(MessageFormat.format(URL_UPLOAD_IMAGE, "accessToken"), param, String.class);
//		return respStr;
		
		 String appDir = null;
			try {
				appDir = ResourceUtils.getURL("classpath:").getPath();
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
			RestTemplate rest = new RestTemplate(); 
		    HttpHeaders headers = new HttpHeaders();
		    if (file == null || file.isEmpty()) {
		    	throw new RuntimeException("未上传文件或上传了空文件");
		    }
		    String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
		    String tempFilePath = appDir + tempFileName;
		    File tempFile = new File(tempFilePath);
		    try {
				file.transferTo(tempFile);
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    FileSystemResource resource = new FileSystemResource(tempFilePath);
		    MediaType mtype = MediaType.parseMediaType("multipart/form-data");
		    headers.setContentType(mtype);
		    String cd = "filename=\"" + file.getOriginalFilename() + "\"";
		    headers.add("Content-Disposition", cd);
		    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
		    param.add("media", resource);
		    HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(param, headers);
		    ResponseEntity<String> result  = rest.postForEntity(MessageFormat.format(URL_UPLOAD_IMAGE, accessToken), files, String.class);
		    try {
		        tempFile.delete();
		    } catch (Exception e) {
		        e.printStackTrace();
		    }
		    return result;
		
	}
	
	@ApiOperation(value = "新增临时素材", notes = "新增临时素材")
	@ApiResponses({ @ApiResponse(code = 200, response = WXAddMaterialResponse.class, message = "新增结果") })
	@PostMapping(value = "/media/upload", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public ResponseEntity<?> uploadMedia(@RequestParam(value = "type", required = true) @ApiParam(value = "类型", required = true) String type,
			@RequestParam(value = "file", required = true) @ApiParam(value = "文件", required = true) MultipartFile file,
			@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = false) String accessToken,
			HttpServletRequest request) {
	    String appDir = null;
		try {
			appDir = ResourceUtils.getURL("classpath:").getPath();
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		RestTemplate rest = new RestTemplate(); 
	    HttpHeaders headers = new HttpHeaders();
	    if (file == null || file.isEmpty()) {
	    	throw new RuntimeException("未上传文件或上传了空文件");
	    }
	    String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
	    String tempFilePath = appDir + tempFileName;
	    LOG.info("tempFilePath"+tempFilePath);
	    File tempFile = new File(tempFilePath);
	    try {
	    	LOG.info("tempFile"+tempFile);
			file.transferTo(tempFile);
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	    FileSystemResource resource = new FileSystemResource(tempFilePath);
	    MediaType mtype = MediaType.parseMediaType("multipart/form-data");
	    headers.setContentType(mtype);
	    String cd = "filename=\"" + file.getOriginalFilename() + "\"";
	    headers.add("Content-Disposition", cd);
	    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
	    param.add("media", resource);
	    HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(param, headers);
	    ResponseEntity<String> result = null;
	    result = rest.postForEntity(MessageFormat.format(URL_UPLOAD_TMP_MEDIA, accessToken, type), files, String.class);
//	    String respStr = rest.postForObject(MessageFormat.format(URL_UPLOAD_TMP_MEDIA, accessToken, type), param, String.class);
	    try {
	        tempFile.delete();
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
	    return result;
	}
	
	@ApiOperation(value = "获取临时素材", notes = "获取临时素材")
	@ApiResponses({ @ApiResponse(code = 200, response = WXAddMaterialResponse.class, message = "新增结果") })
	@GetMapping(value = "/media/get", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String getMedia(@RequestParam(value = "mediaId", required = true) @ApiParam(value = "素材ID", required = true) String mediaId,
			@RequestParam(value = "accessToken", required = true) @ApiParam(value = "访问令牌", required = true) String accessToken) {
	    RestTemplate rest = new RestTemplate();  
	    
	    String respStr = rest.getForObject(MessageFormat.format(URL_GET_TMP_MEDIA, accessToken, mediaId), String.class);
		return respStr;
	}
	
	
	@ApiOperation(value = "新增永久素材", notes = "新增永久素材")
	@ApiResponses({ @ApiResponse(code = 200, response = WXAddMaterialResponse.class, message = "新增结果") })
	@PostMapping(value = "/media/add_material", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public ResponseEntity<?> addMaterial(@RequestParam(value = "type", required = true) @ApiParam(value = "类型", required = true) String type,
			@RequestParam(value = "file", required = true) @ApiParam(value = "文件", required = true) MultipartFile file,
			@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = false) String accessToken) {
//	    RestTemplate rest = new RestTemplate();  
//	    if (file == null || file.isEmpty()) {
//	    	throw new RuntimeException("未上传文件或上传了空文件");
//	    }
//	    FileSystemResource resource = new FileSystemResource(file.getName());
//	    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
//	    param.add("media", resource);
//	    
//	    String respStr = rest.postForObject(MessageFormat.format(URL_ADD_MATERIAL, accessToken, type), param, String.class);
//		return respStr;
		 String appDir = null;
			try {
				appDir = ResourceUtils.getURL("classpath:").getPath();
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
			RestTemplate rest = new RestTemplate(); 
		    HttpHeaders headers = new HttpHeaders();
		    if (file == null || file.isEmpty()) {
		    	throw new RuntimeException("未上传文件或上传了空文件");
		    }
		    String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
		    String tempFilePath = appDir + tempFileName;
		    LOG.info("tempFilePath"+tempFilePath);
		    File tempFile = new File(tempFilePath);
		    try {
		    	LOG.info("tempFile"+tempFile);
		    	FileUtils.copyInputStreamToFile(file.getInputStream(), tempFile);
//				file.transferTo(tempFile);
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    FileSystemResource resource = new FileSystemResource(tempFilePath);
		    MediaType mtype = MediaType.parseMediaType("multipart/form-data");
		    headers.setContentType(mtype);
		    String cd = "filename=\"" + file.getOriginalFilename() + "\"";
		    headers.add("Content-Disposition", cd);
		    MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
		    param.add("media", resource);
		    HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(param, headers);
		    ResponseEntity<String> result = null;
		    result = rest.postForEntity(MessageFormat.format(URL_ADD_MATERIAL, accessToken, type), files, String.class);
		    try {
		        tempFile.delete();
		    } catch (Exception e) {
		        e.printStackTrace();
		    }
		    return result;
	}
	
	@ApiOperation(value = "获取永久素材", notes = "获取永久素材")
	@ApiResponses({ @ApiResponse(code = 200, response = String.class, message = "列表结果") })
	@PostMapping(value = "/material/get", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String getMaterial(@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = false) String accessToken,
			@RequestParam(value = "mediaId", required = true) @ApiParam(value = "素材ID", required = true) String mediaId) {
		RestTemplate rest = new RestTemplate();
		Map<String, Object> body = MapUtil.buildMapKVGen(new Object[][] {
	    	{"media_id", mediaId}
	    }, String.class, Object.class);
	    HttpHeaders headers = new HttpHeaders();  
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);  
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers); 
	    String respStr = rest.postForObject(MessageFormat.format(URL_GET_MATERIAL, accessToken), reqEntity, String.class);
		return respStr;
	}
	
	/*
	 * 
	 * {
  "articles": [{
	       "title": TITLE, //required
	       "thumb_media_id": THUMB_MEDIA_ID, //required
	       "author": AUTHOR,
	       "digest": DIGEST,
	       "show_cover_pic": SHOW_COVER_PIC(0 / 1), //required
	       "content": CONTENT, //required
	       "content_source_url": CONTENT_SOURCE_URL //required
	    },
	    //若新增的是多图文素材，则此处应还有几段articles结构
	 ]
	}
	 * */
	
	@ApiOperation(value = "新增永久图文素材", notes = "新增永久图文素材")
	@ApiResponses({ @ApiResponse(code = 200, response = WXAddMaterialResponse.class, message = "新增结果") })
	@PostMapping(value = "/material/add_news", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String addNews(@RequestBody WeiXinNewsVo weiXinNewsVo) {
	    RestTemplate rest = new RestTemplate();
	    
	    Map<String, Object> article = MapUtil.buildMapKVGen(new Object[][] {
	    	{"title", weiXinNewsVo.getTitle()},
	    	{"thumb_media_id", weiXinNewsVo.getThumbMediaId()},
	    	{"author", weiXinNewsVo.getAuthor()},
	    	{"digest", weiXinNewsVo.getDigest()},
	    	{"show_cover_pic", weiXinNewsVo.getShowCoverPic() == null ? 0 : 1},
	    	{"content", weiXinNewsVo.getContent() == null ? "" : weiXinNewsVo.getContent()},
	    	{"content_source_url", weiXinNewsVo.getContentSrcUrl() == null ? "" : weiXinNewsVo.getContentSrcUrl()}
	    }, String.class, Object.class);
	    Map<String, Object> body = MapUtil.buildMapKVGen(new Object[][] {{"articles", new Object[] {article}}}, String.class, Object.class);
	    HttpHeaders headers = new HttpHeaders();  
	    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);  
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers); 
	    String respStr = rest.postForObject(MessageFormat.format(URL_ADD_NEWS, weiXinNewsVo.getAccessToken()), reqEntity, String.class);
		return respStr;
	}
	
	@ApiOperation(value = "获取素材列表", notes = "获取素材列表")
	@ApiResponses({ @ApiResponse(code = 200, response = String.class, message = "列表结果") })
	@PostMapping(value = "/material/batchget_material", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String getNews(@RequestParam(value = "accessToken", required = false) @ApiParam(value = "访问令牌", required = false) String accessToken,
			@RequestParam(value = "type", required = true) @ApiParam(value = "类型", required = true) String type,
			@RequestParam(value = "offset", required = true) @ApiParam(value = "偏移量", required = true) Integer offset,
			@RequestParam(value = "count", required = true) @ApiParam(value = "数量", required = true) Integer count) {
		RestTemplate rest = new RestTemplate();
		Map<String, Object> body = MapUtil.buildMapKVGen(new Object[][] {
	    	{"type", type},
	    	{"offset", offset},
	    	{"count", count}
	    }, String.class, Object.class);
	    HttpHeaders headers = new HttpHeaders();  
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);  
		headers.add("Accept", MediaType.APPLICATION_JSON_UTF8_VALUE);
		HttpEntity<String> reqEntity = new HttpEntity<String>(JsonUtil.asString(body), headers); 
	    String respStr = rest.postForObject(MessageFormat.format(URL_GET_NEWS, accessToken), reqEntity, String.class);
		return respStr;
	}
	
	@ApiOperation(value = "获取素材总数", notes = "获取素材总数")
	@ApiResponses({ @ApiResponse(code = 200, response = WXAddMaterialResponse.class, message = "新增结果") })
	@GetMapping(value = "/material/count", produces = { MediaType.APPLICATION_JSON_UTF8_VALUE })
	@ResponseBody
	public String getMaterialCount(@RequestParam(value = "accessToken", required = true) @ApiParam(value = "访问令牌", required = true) String accessToken) {
	    RestTemplate rest = new RestTemplate();  
	    
	    String respStr = rest.getForObject(MessageFormat.format(URL_GET_MATERIAL_COUNT, accessToken), String.class);
		return respStr;
	}
}
